package com.jrx.anytxn.accounting.aspect;


import com.jrx.anytxn.common.uitl.JsonUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * 切面记录接口调用信息
 *
 * @author : zhenghaopu
 * 2019/10/29
*/
@Component
@Aspect
public class ApiLogAspect {

    private static final Logger logger = LoggerFactory.getLogger(ApiLogAspect.class);

    /**
     * 所有controller包及子包下的所有公共方法
     */
    @Pointcut("execution(public * com.jrx.anytxn.accounting.controller..*.*(..)) ")
    public void pointCutType() {
        // default implementation ignored
    }

    /**
     * 对全局异常做切面
     */
    @Pointcut("@within(org.springframework.web.bind.annotation.ControllerAdvice)")
    public void pointCutExceptionHandler() {
        // default implementation ignored
    }

    @Around(value = "pointCutType()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        //获取方法全路径
        String methodPath=getMethodPath(pjp);
        Object[] objects = pjp.getArgs();
        String req = JsonUtils.obj2json(objects);
        logger.info("[{}}方法执行开始，请求报文[{}]",methodPath,req);
        //执行并获取返回
        Object result = pjp.proceed();
        String returnStr = JsonUtils.obj2json(result);
        logger.info("[{}}方法执行结束，返回报文[{}]",methodPath,returnStr);
        return result;
    }

    @AfterReturning(value = "pointCutExceptionHandler()",returning = "result")
    public void afterRunning(JoinPoint pjp,Object result) throws Throwable{
        String returnStr = JsonUtils.obj2json(result);
        logger.error("执行异常，异常[{}]",returnStr);
    }

    /**
     * 获取执行方法全路径
     * 格式：类.方法
     *
     * @param pjp 切点上下文
     * @return 方法全路径
     */
    private String getMethodPath(JoinPoint pjp){
        Signature signature = pjp.getSignature();
        String name =signature.getName();
        String simpleName = signature.getDeclaringType().getSimpleName();
        return String.format("%s.%s", simpleName, name);
    }
}
